package com.cennavi.minemap.service;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.cennavi.minemap.bean.SoluBean;
import com.cennavi.minemap.bean.SourceBean;
import com.cennavi.minemap.bean.UploadBean;
import com.cennavi.minemap.bean.UserSourceBean;
import com.cennavi.minemap.dao.SoluDao;
import com.cennavi.minemap.dao.SourceDao;
import com.cennavi.minemap.dao.TokenDao;
import com.cennavi.minemap.dao.UploadDao2;
import com.cennavi.minemap.util.Constants;
import com.cennavi.minemap.util.DateTimeUtil;
import com.cennavi.minemap.util.FileUtil;
import com.cennavi.minemap.util.GeoUtil;
import com.cennavi.minemap.tool.ParseCsvFile;
import com.cennavi.minemap.tool.ParseFactory;
import com.cennavi.minemap.tool.ParseFile;
import com.vividsolutions.jts.geom.Geometry;

@Service
@ComponentScan(basePackages = { "com.cennavi.minemap.dao" })
@PropertySource(value = { "classpath:application.properties" })
public class UploadService {
	@Autowired
	private UploadDao2 uploadDao2;

	@Autowired
	private SourceDao sourceDao;

	@Autowired
	private SoluDao soluDao;

	@Autowired
	private TokenDao tokenDao;

	@Value("${spring.upload.root}")
	private String root;

	@Value("${spring.upload.pyScript}")
	private String pyScript;

	@Value("${spring.upload.unzipPath}")
	private String unzipPath;

	@Value("${spring.upload.pg.host}")
	private String host;

	@Value("${spring.upload.pg.port}")
	private String port;

	@Value("${spring.upload.pg.database}")
	private String database;

	@Value("${spring.upload.pg.username}")
	private String username;

	@Value("${spring.upload.pg.password}")
	private String password;

	public int createTable(Integer userId, Integer uploadId) {
		return uploadDao2.createUploadDetail(userId, uploadId);
	}

	@Transactional(rollbackFor = Exception.class)
	public int uploadFile(UploadBean uploadBean, SourceBean sourceBean) throws IOException {
		MultipartFile file = uploadBean.getFile();
		int uploadId = 0;
		if (!file.isEmpty()) {
			// UPLOAD表插入数据
			uploadBean.setFileSize(file.getSize());
			String fileName = uploadBean.getFile().getOriginalFilename().split("\\.")[0];
			String suffix = uploadBean.getFile().getOriginalFilename().split("\\.")[1];
			uploadBean.setName(fileName + "_" + DateTimeUtil.getNow("YYYYMMddHHmmss") + "." + suffix);

			uploadId = uploadDao2.insert(uploadBean);
			uploadDao2.createUploadDetail(uploadBean.getUserId(), uploadId);

			// 文件上传
			String path = root + File.separator + uploadBean.getUserId();
			FileUtil.mkdir(path);

			// String name = uploadBean.getName() +
			// DateTimeUtil.getNow("YYYYMMddHHmmss");

			String fullPath = path + File.separator + uploadBean.getName();
			InputStream inputStream = file.getInputStream();
			OutputStream outputStream = new FileOutputStream(fullPath);
			System.out.println(file.getSize());
			long bytesWritten = 0;
			int byteCount = 0;
			byte[] bytes = new byte[1024];
			while ((byteCount = inputStream.read(bytes)) != -1) {
				outputStream.write(bytes, 0, byteCount);
				bytesWritten += byteCount;
				outputStream.flush();
			}
			inputStream.close();
			outputStream.close();

			// UPLOAD表更新状态
			String now = DateTimeUtil.getNow();
			UploadBean updateUploadBean = new UploadBean();
			updateUploadBean.setId(uploadId);
			updateUploadBean.setStatus(Constants.USER_UPLOAD_STATUS_UPLOAD);
			updateUploadBean.setUploadSize(bytesWritten);
			updateUploadBean.setUploadTime(now);
			updateUploadBean.setPath(fullPath);
			uploadDao2.update(updateUploadBean);

			// 插入SOURCE表
			sourceBean.setUploadId(uploadId);
			sourceBean.setType("vector");
			sourceBean.setCreateTime(now);

			JSONObject content = new JSONObject();

			JSONArray tiles = new JSONArray();

			tiles.add(Constants.USER_UPLOAD_CONTENT.replace("{uploadId}", String.valueOf(uploadId)).replace("{userId}",
					uploadBean.getUserId().toString()));

			content.put("tiles", tiles);

			sourceBean.setContent(content.toJSONString());

			sourceBean.setMinZoom(Constants.USER_UPLOAD_MINZOOM);
			sourceBean.setMaxZoom(Constants.USER_UPLOAD_MAXZOOM);

			JSONArray layerDesc = new JSONArray();
			JSONObject layerDescO = new JSONObject();

			int type = uploadBean.getType();

			if (type == Constants.USER_UPLOAD_TYPE_POINT) {
				layerDescO.put("type", "symbol");
			}
			if (type == Constants.USER_UPLOAD_TYPE_LINE) {
				layerDescO.put("type", "line");
			}
			if (type == Constants.USER_UPLOAD_TYPE_FACE) {
				layerDescO.put("type", "fill");
			}

			layerDescO.put("attrs", new JSONArray());
			layerDescO.put("name", sourceBean.getName());
			layerDescO.put("id", "upload_" + uploadId);
			layerDesc.add(layerDescO);

			sourceBean.setLayerDesc(layerDesc.toJSONString());
			sourceBean.setCode("upload_" + uploadId);
			sourceBean.setUploadId(uploadId);
			sourceBean.setIcon("upload" + type);
			sourceBean.setMinZoom(10d);
			sourceBean.setMaxZoom(17.5);
			sourceBean.setIsBind(1);
			int sourceId = sourceDao.insert(sourceBean);

			int userId = uploadBean.getUserId();

			// 插入USER_SOURCE表
			UserSourceBean userSourceBean = new UserSourceBean();
			userSourceBean.setUserId(userId);
			userSourceBean.setSourceIds(Arrays.asList(sourceId));
			sourceDao.insertUserSource(userSourceBean);

			Map<String, String> parameterMap = new HashMap<String, String>();
			parameterMap.put("host", host);
			parameterMap.put("port", port);
			parameterMap.put("database", database);
			parameterMap.put("username", username);
			parameterMap.put("password", password);

			parameterMap.put("pyScript", pyScript);
			parameterMap.put("unzipPath", unzipPath);

			ParseFactory factory = new ParseFactory(parameterMap);

			Map<String, Integer> rMap = factory.createParseFile(suffix).parse(fullPath, uploadDao2,
					uploadBean.getType(), userId, uploadId);

			UploadBean finalUploadBean = new UploadBean();
			finalUploadBean.setId(uploadId);
			finalUploadBean.setFileLine(rMap.get("fileLine"));
			finalUploadBean.setSuccLine(rMap.get("succLine"));
			finalUploadBean.setStatus(Constants.USER_UPLOAD_STATUS_PARSE);
			finalUploadBean.setFailLine(rMap.get("fileLine") - rMap.get("succLine"));
			uploadDao2.update(finalUploadBean);
		}

		return uploadId;
	}

	public List<UploadBean> queryById(int id) {
		return Arrays.asList(uploadDao2.queryById(id));
	}

	public List<UploadBean> queryByUserId(int userId) {
		return uploadDao2.queryByUserId(userId);
	}

	public int test(Integer userId) {
		ParseFile parse = new ParseCsvFile();
		parse.parse("F:\\csv_template.csv", uploadDao2, 1, userId, 1);
		return 0;
	}

	@Transactional
	public int updateDetail(Integer userId, Integer uploadId, JSONObject json) {
		JSONArray addArray = json.getJSONArray("add");
		JSONArray modArray = json.getJSONArray("mod");
		JSONArray delArray = json.getJSONArray("del");

		boolean addFlag = false;
		if (addArray != null && addArray.size() > 0) {
			List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();

			for (int i = 0; i < addArray.size(); i++) {
				Map<String, Object> map = new HashMap<String, Object>();
				JSONObject addJson = addArray.getJSONObject(i);
				map.put("attr", addJson.getJSONObject("attr").toJSONString());

				Geometry geom = null;
				String geomStr = null;

				try {
					geom = GeoUtil.readGeojson(addJson.getString("geom"));
					geomStr = GeoUtil.geometry2WKT(geom);
				} catch (Exception e) {
					e.printStackTrace();
				}
				map.put("geom", geomStr);

				list.add(map);
			}
			addFlag = uploadDao2.addUploadDetail(list, userId, uploadId);
		} else {
			addFlag = true;
		}

		boolean modFlag = false;
		if (modArray != null && modArray.size() > 0) {
			modFlag = uploadDao2.modUploadDetail(modArray, userId, uploadId);
		} else {
			modFlag = true;
		}

		boolean delFlag = false;
		if (delArray != null && delArray.size() > 0) {
			delFlag = uploadDao2.delUploadDetail(delArray, userId, uploadId);
		} else {
			delFlag = true;
		}

		if (addFlag && modFlag && delFlag)
			return 0;
		else
			return -1;
	}

	/**
	 * 次方法与SoluService中的方法重复因为拆服务所以分开
	 * 
	 * @param id
	 * @return
	 */
	public List<SoluBean> queryByIdWithToken(int id) {
		SoluBean soluBean = soluDao.queryById(id);
		List<String> list = tokenDao.queryTokenSoluBySoluId(id);
		soluBean.setTokens(list);
		return Arrays.asList(soluBean);
	}

	public List<JSONObject> queryUploadDetailList(Integer userId, Integer uploadId) {
		return uploadDao2.queryUploadDetailList(userId, uploadId);
	}

	public List<JSONObject> queryUploadDetailById(Integer userId, Integer uploadId, Integer id) {
		return uploadDao2.queryUploadDetailById(userId, uploadId, id);
	}

	public Integer querySoluId(Integer uploadId) {
		return uploadDao2.querySoluId(uploadId);
	}

	public Integer saveSoluId(Integer uploadId, Integer soluId) {
		return uploadDao2.saveSoluId(uploadId, soluId);
	}
}
